/*
 * Copyright 2008 Max Kugland
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.splink.library.tree {
	import org.splink.library.utils.ArrayUtils;

	/**
	 * Represents a node of the <code>Tree</code> class. <code>Node</code> is also a container for
	 * a generic data object.
	 * 
	 * @see org.splink.library.tree.Tree
	 */
	public class Node implements INode{
		private var _id : String;
		private var _data : *;
		private var _children : Array;
		private var _parent : INode;

		/**
		 * @param id this <code>Node</code>'s id
		 * @param data this <code>Node</code>'s parent <code>Node</code>
		 * @param data the data within the <code>Node</code>
		 */
		public function Node(id : String, data : * = null) {
			_id = id;
       		_data = data;
		}

		/**
		 * @inheritDoc
		 */
		public function get children() : Array {
			if (_children == null) {
				return new Array();
			}
			return _children.concat();
		}

		/**
		 * @inheritDoc
		 */
		public function get isLeaf() : Boolean {
			return (_children == null) || (_children.length == 0);
		}

		/**
		 * @inheritDoc
		 */
		public function add(n : INode) : INode {
			if (_children == null) {
				_children = new Array();
			}
			n.parent = this;
			_children.push(n);
			return n;
		}
		
		/**
		 * @inheritDoc
		 */
		public function remove(n : INode) : INode {
			if (_children == null) {
				_children = new Array();
			}
			n.parent = null;
			ArrayUtils.remove(_children, n);
			return n;
		}

		/**
		 * @inheritDoc
		 */
		public function get data() : * {
			return _data;
		}

		/**
		 * @inheritDoc
		 */
		public function set data(data : *) : void {
			_data = data;
		}

		/**
		 * @inheritDoc
		 */
		public function get layer() : uint {
			return parent != null ? _parent.layer + 1 : 0;
		}

		/**
		 * @inheritDoc
		 */
		public function get parent() : INode {
			return _parent;
		}

		/**
		 * @inheritDoc
		 */
		public function set parent(p : INode) : void {
			_parent = p;
		}

		/**
		 * @inheritDoc
		 */
		public function get id() : String {
			return _id;
		}
		
		/**
		 * @return a String representation of the node
		 */
		public function toString() : String {
			var parentId : String = parent != null ? _parent.id : null;
			return "org.splink.library.tree.Node id: " + id + " parentId: " + parentId + " layer: " + layer + " data: " + data;
		}

        /**
		 * Finalizes the <code>INode</code> and invokes finalize on all children.
		 * 
		 * @inheritDoc
		 */
		public function finalize() : void {
			for each (var child : INode in _children) {
				child.finalize();
			}
			
			_children = null;
			_data = null;
			_parent = null;
		}
	}
}